﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace ShellAnywhere.Model
{
	public class Token<T> : IToken<T> 
		where T : class, IParam
	{
		#region ctors
		public Token(int dot, List<T> children)
		{
			Init(dot, children);
		}
		public Token(params T[] children) : this(0, children) { }
		public Token(int dot, params T[] children)
		{
			Init(dot, children);
		}
		//public Token(TargetList children) : this(0, children) { }
		//public Token(int dot, TargetList children)
		//{
		//    Init(dot, children);
		//}
		public Token(List<ITarget> children) : this(0, children) { }
		public Token(int dot, List<ITarget> children)
		{
			Init(dot, children);
		}
		#endregion ctors

		#region props
		public int Dot { get { return _Dot; } }
		public char LastChar
		{
			get
			{
				char c = '\0';
				if (Child != null)
					c = Child.CharAt(_Dot - 1);
				return c;
			}
		}
		public char CharAtDot
		{
			get
			{
				char c = '\0';
				if (Child != null)
					c = Child.CharAt(_Dot);
				return c;
			}
		}
		public T Child
		{
			get
			{
				T child = default(T);
				if (HasChildren)
					child = _Children[0];
				return child;
			}
		}
		public List<T> Children { get { return _Children; } }		
		public int Count { get { return (_Children != null) ? _Children.Count : 0; } }
		public bool IsMatched { get { return HasOneChild && Child.IsMatched(_Dot); } }
		public bool HasChildren { get { return Count > 0; } }
		public bool HasOneChild { get { return Count == 1; } }
		public List<T> Matched 
		{
			get
			{
				List<T> matched = new List<T>();
				if (HasChildren)
				{
					foreach (T child in _Children)
					{
						if (child.IsMatched(_Dot))
							matched.Add(child);
					}
				}
				return matched;
			}
		}
		public List<T> Unmatched
		{
			get
			{
				List<T> unmatched = new List<T>();
				if (HasChildren)
				{
					foreach (T child in _Children)
					{
						if (!child.IsMatched(_Dot))
							unmatched.Add(child);
					}
				}
				return unmatched;
			}
		}
		#endregion props

		#region methods
		public virtual bool Init(int dot, object enumerable)
		{
			bool result = false;
			IEnumerable e = enumerable as IEnumerable;
			if (dot >= 0 && e != null)
			{
				_Dot = dot;
				_Children = new List<T>();

				foreach (object o in e)
				{
					T t = o as T;
					_Children.Add(t);
				}
				if (dot > 0 && _Children.Count > 1)
				{
					string matched = _Children[0].Matched(dot);
					for (int i = 1; i < _Children.Count; ++i)
					{
						if (matched != _Children[i].Matched(dot))
						{
							result = false;
							break;
						}
					}
				}
			}		

			return result;
		}
		public IToken<T> Constrain(Func<T, bool> predicate)
		{
			throw new NotImplementedException();
		}

		public IToken<T> Constrain(Func<T, int, bool> predicate)
		{
			throw new NotImplementedException();
		}
		#endregion methods

		#region events
		#endregion events

		#region fields
		private int _Dot = 0;
		private List<T> _Children = new List<T>();
		#endregion fields
	}
}
